#include "PropertyGroup.h"
#include "../Operations/OperationManager.h"
#include "../View/View.h"

///<************************************************************************************************************>
///<************************************* region CONSTANTS DEFINITION ******************************************>
///<************************************************************************************************************>

const QString CIGui::PropertyGroup::STYLE_SHEET = QString (
                                                        "QObject {"
                                                            "font-family: sans-serif;"
                                                            "font-size: 8pt;"
                                                        "}"
                                                        "QLineEdit {"
                                                            "font-family: sans-serif;"
                                                            "font: bold;"
                                                            "color: gray;"
                                                            "border: 1px solid gray;"
                                                            "border-radius: 6px;"
                                                            "padding: 1px 1px 1px 1px;"
                                                            "background-color: white;"
                                                            "margin: 0px 0px 0px 0px;"
                                                        "}"

                                                        "QLabel {"
                                                            "font-family: sans-serif;"
                                                            "font: bold;"
                                                            "color: white;"
                                                            "border: 2px solid darkgray;"
                                                            "border-radius: 6px;"
                                                            "padding: 1px 10px 1px 10px;"
                                                            "margin: 0px 0px 0px 10px;"
                                                        "}"

                                                         "QPushButton {"
                                                             "border: 2px solid lightgray;"
                                                             "border-radius: 6px;"
                                                             "padding: 5px 10px 5px 10px;"
                                                             "background-color: qlineargradient(x1: 0, y1: 0, x2: 0, y2: 1,"
                                                                                               "stop: 0 #f6f7fa, stop: 1 #dadbde);"
                                                             "min-width: 80px;"
                                                             "max-width: 80px;"
                                                         "}"

                                                         "QPushButton:pressed {"
                                                             "background-color: qlineargradient(x1: 0, y1: 0, x2: 0, y2: 1,"
                                                                                               "stop: 0 #dadbde, stop: 1 #f6f7fa);"
                                                             "padding: 6px 10px 5px 12px;"
                                                         "}"

                                                         "QPushButton:flat {"
                                                             "border: none;" /* no border for a flat push button */
                                                         "}"

                                                         "QPushButton:default {"
                                                             "border-color: navy;" /* make the default button prominent */
                                                         "}"
                                                     );
/***************************************************************************************************************
************************************** endregion CONSTANTS DEFINITION ******************************************
****************************************************************************************************************/






/// <summary>
/// Constructor
/// </summary>
/// <param name="n"> The name of the property group </param>
/// <param name="parent"> The widget parent </param>
CIGui::PropertyGroup::PropertyGroup (CIOps::ActionOpCreation* act, QString n, QWidget* parent)
: QGroupBox (n+" Properties",parent), name (n), operationAction (act) {

    setSizePolicy (QSizePolicy (QSizePolicy::Expanding, QSizePolicy::Expanding));
    setStyleSheet (STYLE_SHEET);
    setObjectName (name+" Properties");

    this->setLayout (new QVBoxLayout());

    setVisible (false);

    connect (act, SIGNAL (toggled (bool)), this, SLOT (setVisible (bool)));
    connect (act, SIGNAL (toggled (bool)), this, SLOT (SetAllProperties (bool)));
}

/// <summary>
/// Destructor
/// </summary>
CIGui::PropertyGroup::~PropertyGroup() {}








///<************************************************************************************************************>
///<****************************************** region Public SLOTS *********************************************>
///<************************************************************************************************************>

/// <summary>
/// Slot method to retrieve and set the values of
/// the properties of the current operation
/// </summary>
void CIGui::PropertyGroup::SetAllProperties (bool flag) {
    if (!flag)
        return;

    //Retrieving the properties
    QObject* xLineEdit = child ("X");
    if (xLineEdit)
        SetX (((QLineEdit*)xLineEdit)->text());

    QObject* yLineEdit = child ("Y");
    if (yLineEdit)
        SetY (((QLineEdit*)yLineEdit)->text());

    QObject* zLineEdit = child ("Z");
    if (zLineEdit)
        SetZ (((QLineEdit*)zLineEdit)->text());

    QObject* centreOfMass = child ("CenterOfMass");
    if (centreOfMass)
        CIOps::OperationManager::CenterOfMass = ((QRadioButton*)centreOfMass)->isChecked();

    QObject* origin = child ("Origin");
    if (origin)
        CIOps::OperationManager::Origin = ((QRadioButton*)origin)->isChecked();

    QObject* userPoint = child ("UserPoint");
    if (userPoint)
        CIOps::OperationManager::UserPoint = ((QRadioButton*)userPoint)->isChecked();

    QObject* stacksLineEdit = child ("Stacks");
    if (stacksLineEdit)
        SetStacks (((QLineEdit*)stacksLineEdit)->text());

    QObject* slicesLineEdit = child ("Slices");
    if (slicesLineEdit)
        SetSlices (((QLineEdit*)slicesLineEdit)->text());

    QObject* ignoreBackfaces = child ("IgnoreBackfaces");
    if (ignoreBackfaces)
        CIOps::OperationManager::IgnoreBackfaces = ((QCheckBox*)ignoreBackfaces)->isChecked();

    QObject* thicknessLineEdit = child ("Thickness");
    if (thicknessLineEdit)
        SetThickness (((QLineEdit*)thicknessLineEdit)->text());
}


/// <summary>
/// Slot method to set the X property
/// </summary>
void CIGui::PropertyGroup::SetX (const QString& x) {
    CIOps::OperationManager::X_Y_Z_Params.x = x.toFloat();
}

/// <summary>
/// Slot method to set the Y property
/// </summary>
void CIGui::PropertyGroup::SetY (const QString& y) {
    CIOps::OperationManager::X_Y_Z_Params.y = y.toFloat();
}

/// <summary>
/// Slot method to set the Z property
/// </summary>
void CIGui::PropertyGroup::SetZ (const QString& z) {
    CIOps::OperationManager::X_Y_Z_Params.z = z.toFloat();
}

/// <summary>
/// Slot method to set the CentreOfMass property
/// </summary>
void CIGui::PropertyGroup::SetCenterOfMass (bool centerOfMass) {
    CIOps::OperationManager::CenterOfMass = centerOfMass;
    emit PropertyChanged();
}

/// <summary>
/// Slot method to set the Origin property
/// </summary>
void CIGui::PropertyGroup::SetOrigin (bool origin) {
    CIOps::OperationManager::Origin = origin;
    emit PropertyChanged();
}

/// <summary>
/// Slot method to set the UserPoint property
/// </summary>
void CIGui::PropertyGroup::SetUserPoint(bool userPoint) {
    CIOps::OperationManager::UserPoint = userPoint;
    emit PropertyChanged();
}

/// <summary>
/// Slot method to do the operation associated with this property group
/// </summary>
void CIGui::PropertyGroup::SendOperationRequest() {
    if (operationAction) {
        emit OperationRequest (operationAction->GetOperationID());
    }
}


/// <summary>
/// Slot method to set the Stacks property
/// </summary>
void CIGui::PropertyGroup::SetStacks (const QString& stacks) {
    CIOps::OperationManager::Stacks = stacks.toInt();
    emit PropertyChanged();
}


/// <summary>
/// Slot method to set the Slices property
/// </summary>
void CIGui::PropertyGroup::SetSlices (const QString& slices) {
    CIOps::OperationManager::Slices = slices.toInt();
    emit PropertyChanged();
}

/// <summary>
/// Slot method to set the IgnoreBackfaces property
/// </summary>
void CIGui::PropertyGroup::SetIgnoreBackfaces (bool b) {
    CIOps::OperationManager::IgnoreBackfaces = b;
    emit PropertyChanged();
}

/// <summary>
/// Slot method to set the Thickness property
/// </summary>
void CIGui::PropertyGroup::SetThickness (const QString& thickness) {
    CIOps::OperationManager::Thickness = thickness.toFloat();
    emit PropertyChanged();
}
/***************************************************************************************************************
******************************************* endregion Public SLOTS *********************************************
****************************************************************************************************************/










///<************************************************************************************************************>
///<**************************************** region Utility Methods ********************************************>
///<************************************************************************************************************>

void CIGui::PropertyGroup::Add_X_Y_Z_Properties (QString& default_value) {
    QRegExpValidator* validator = new QRegExpValidator (QRegExp ("[-]?[0-9]+[.]?[0-9]*"), 0);

    QHBoxLayout* xLayout = new QHBoxLayout();
    xLayout->setSpacing (10);
    xLayout->addWidget (new QLabel ("X"));
    QLineEdit* xLineEdit = new QLineEdit();
    xLineEdit->setObjectName ("X");
    xLineEdit->setValidator (validator);
    xLineEdit->setText (default_value);
    xLayout->addWidget (xLineEdit);
    QWidget* xWidget = new QWidget();
    xWidget->setLayout (xLayout);
    xWidget->setStyleSheet ("QLabel {"
                                "background-color: qlineargradient(spread:pad, x1:0, y1:0, x2:1, y2:0, "
                                                                "stop:0 rgba(170, 0, 0, 255), "
                                                                "stop:1 rgba(255, 255, 255, 255));"
                            "}"
                            );

    QHBoxLayout* yLayout = new QHBoxLayout();
    yLayout->setSpacing (10);
    yLayout->addWidget (new QLabel ("Y"));
    QLineEdit* yLineEdit = new QLineEdit();
    yLineEdit->setObjectName ("Y");
    yLineEdit->setValidator (validator);
    yLineEdit->setText (default_value);
    yLayout->addWidget (yLineEdit);
    QWidget* yWidget = new QWidget();
    yWidget->setLayout (yLayout);
    yWidget->setStyleSheet ("QLabel {"
                                "background-color: qlineargradient(spread:pad, x1:0, y1:0, x2:1, y2:0, "
                                                                "stop:0 rgba(0, 170, 0, 255), "
                                                                "stop:1 rgba(255, 255, 255, 255));"
                            "}"
                            );

    QHBoxLayout* zLayout = new QHBoxLayout();
    zLayout->setSpacing (10);
    zLayout->addWidget (new QLabel ("Z"));
    QLineEdit* zLineEdit = new QLineEdit();
    zLineEdit->setObjectName ("Z");
    zLineEdit->setValidator (validator);
    zLineEdit->setText (default_value);
    zLayout->addWidget (zLineEdit);
    QWidget* zWidget = new QWidget();
    zWidget->setLayout (zLayout);
    zWidget->setStyleSheet ("QLabel {"
                                "background-color: qlineargradient(spread:pad, x1:0, y1:0, x2:1, y2:0, "
                                                                "stop:0 rgba(0, 0, 170, 255), "
                                                                "stop:1 rgba(255, 255, 255, 255));"
                            "}"
                            );

    QVBoxLayout* layout = (QVBoxLayout*)this->layout();
    layout->addWidget (xWidget);
    layout->addWidget (yWidget);
    layout->addWidget (zWidget);
    QPushButton* pushButton = new QPushButton (name);
    pushButton->setObjectName ("PushButton");
    layout->addWidget (pushButton, 0, Qt::AlignCenter);


    connect (xLineEdit, SIGNAL (textChanged (const QString&)), this, SLOT (SetX (const QString&)));
    connect (yLineEdit, SIGNAL (textChanged (const QString&)), this, SLOT (SetY (const QString&)));
    connect (zLineEdit, SIGNAL (textChanged (const QString&)), this, SLOT (SetZ (const QString&)));
    connect (pushButton, SIGNAL (clicked (bool)), this, SLOT (SendOperationRequest()));
}

void CIGui::PropertyGroup::AddReferencePointProperties() {
    QWidget* radioButtons = new QWidget();
    radioButtons->setStyleSheet ("QObject {"
                                    "font-family: sans-serif;"
                                    "font-size: 8pt;"
                                 "}");
    QVBoxLayout* radioButtonsLayout = new QVBoxLayout();
    radioButtons->setLayout (radioButtonsLayout);

    QRadioButton* CenterOfMass = new QRadioButton ("Center Of Mass");
    CenterOfMass->setObjectName ("CenterOfMass");
    CenterOfMass->setChecked (true);
    radioButtonsLayout->addWidget (CenterOfMass);

    QRadioButton* Origin = new QRadioButton ("Origin");
    Origin->setObjectName ("Origin");
    radioButtonsLayout->addWidget (Origin);

    QRadioButton* UserPoint = new QRadioButton ("User Point");
    UserPoint->setObjectName ("UserPoint");
    radioButtonsLayout->addWidget (UserPoint);

    QVBoxLayout* layout = (QVBoxLayout*)this->layout();
    layout->insertWidget (0, radioButtons, 0, Qt::AlignCenter);

    connect (CenterOfMass, SIGNAL (toggled (bool)), this, SLOT (SetCenterOfMass (bool)));
    connect (Origin, SIGNAL (toggled (bool)), this, SLOT (SetOrigin (bool)));
    connect (UserPoint, SIGNAL (toggled (bool)), this, SLOT (SetUserPoint (bool)));
}

void CIGui::PropertyGroup::AddCreationProperties(QString default_stacks, QString default_slices) {
    QRegExpValidator* validator = new QRegExpValidator (QRegExp ("[1-2]?[0-9]"), 0);

    QHBoxLayout* horizLayout = new QHBoxLayout();
    horizLayout->setSpacing (1);
    horizLayout->addWidget (new QLabel ("Stacks"));
    QLineEdit* stacksLineEdit = new QLineEdit();
    stacksLineEdit->setObjectName ("Stacks");
    stacksLineEdit->setValidator (validator);
    stacksLineEdit->setText (default_stacks);
    horizLayout->addWidget (stacksLineEdit);

    //QHBoxLayout* slicesLayout = new QHBoxLayout();
    //slicesLayout->setSpacing (10);
    horizLayout->addWidget (new QLabel ("Slices"));
    QLineEdit* slicesLineEdit = new QLineEdit();
    slicesLineEdit->setObjectName ("Slices");
    slicesLineEdit->setValidator (validator);
    slicesLineEdit->setText (default_slices);
    horizLayout->addWidget (slicesLineEdit);


    QWidget* widget = new QWidget();
    widget->setLayout (horizLayout);
    widget->setStyleSheet ("QLabel {"
                                    "background-color: rgba(0,0,0,0);"
                                    "border: 0px;"
                                    "border-radius: 0px;"
                                    "color: black;"
                                    "font-family: sans-serif;"
                                    "font: normal;"
                                    "margin: 0px 0px 0px 0px;"
                                    "padding: 0px 5px 0px 5px;"
                                "}"
                                );

    connect (stacksLineEdit, SIGNAL (textChanged (const QString&)), this, SLOT (SetStacks (const QString&)));
    connect (slicesLineEdit, SIGNAL (textChanged (const QString&)), this, SLOT (SetSlices (const QString&)));


    QVBoxLayout* layout = (QVBoxLayout*)this->layout();
    layout->addWidget (widget);
}

void CIGui::PropertyGroup::AddIgnoreBackfacesProperty() {
    QCheckBox* ignoreBackfacesCheckBox = new QCheckBox ("Ignore Backfaces");
    ignoreBackfacesCheckBox->setObjectName ("IgnoreBackfaces");
    ignoreBackfacesCheckBox->setChecked (false);
    ignoreBackfacesCheckBox->setStyleSheet ("QCheckBox {"
                                                "margin: 6px 30px 6px 30px;"
                                            "}"
                                            "QObject {"
                                                "font-family: sans-serif;"
                                                "font-size: 8pt;"
                                             "}");

    connect (ignoreBackfacesCheckBox, SIGNAL (toggled (bool)), this, SLOT (SetIgnoreBackfaces (bool)));

    QVBoxLayout* layout = (QVBoxLayout*)this->layout();
    layout->addWidget (ignoreBackfacesCheckBox);
}

void CIGui::PropertyGroup::AddThicknessProperty (QString default_thickness) {
    QRegExpValidator* validator = new QRegExpValidator (QRegExp ("[1-5][.][0-9]*"), 0);

    QHBoxLayout* thicknessLayout = new QHBoxLayout();
    thicknessLayout->setSpacing (7);
    thicknessLayout->addWidget (new QLabel ("Thickness"));
    QLineEdit* thicknessLineEdit = new QLineEdit();
    thicknessLineEdit->setObjectName ("Thickness");
    thicknessLineEdit->setValidator (validator);
    thicknessLineEdit->setText (default_thickness);
    thicknessLayout->addWidget (thicknessLineEdit);
    QWidget* thicknessWidget = new QWidget();
    thicknessWidget->setLayout (thicknessLayout);
    this->setStyleSheet (
                            "QObject {"
                                "font-family: sans-serif;"
                                "font-size: 8pt;"
                            "}"
                            "QLabel {"
                                "background-color: rgba(0,0,0,0);"
                                "border: 0px;"
                                "border-radius: 0px;"
                                "height: 3px;"
                                "color: black;"
                                "font-family: sans-serif;"
                                "font: normal;"
                                "margin: 0px 0px 0px 0px;"
                            "}"
                            "QLineEdit {"
                                "margin: 0px 0px 0px 0px;"
                                "height: 10px;"
                                "max-width: 100px;"
                                "font-family: sans-serif;"
                                "font: bold;"
                                "color: gray;"
                                "border: 1px solid gray;"
                                "border-radius: 6px;"
                                "padding: 1px 1px 1px 1px;"
                                "background-color: white;"
                            "}"
                            );

    connect (thicknessLineEdit, SIGNAL (textChanged (const QString&)), this, SLOT (SetThickness (const QString&)));

    QVBoxLayout* layout = (QVBoxLayout*)this->layout();
    layout->addWidget (thicknessWidget);
    layout->setSpacing (0);
}
/***************************************************************************************************************
***************************************** endregion Utility Methods ********************************************
****************************************************************************************************************/
